home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 November: Tool Chest / Dev.CD Nov 98 TC.toast / Sample Code / Text / SimpleText Sample / Clipboard.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-10-17  |  11.1 KB  |  396 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        Clipboard.c
  3.  
  4.     Contains:    Clipboard support for simple text application.
  5.  
  6.     Version:    SimpleText 1.4 or later
  7.  
  8. ** Copyright 1993-1996 Apple Computer. All rights reserved.
  9. **
  10. **    You may incorporate this sample code into your applications without
  11. **    restriction, though the sample code has been provided "AS IS" and the
  12. **    responsibility for its operation is 100% yours.  However, what you are
  13. **    not permitted to do is to redistribute the source as "DSC Sample Code"
  14. **    after having made changes. If you're going to re-distribute the source,
  15. **    we require that you make it clear in the source that the code was
  16. **    descended from Apple Sample Code, but that you've made changes.
  17.  
  18. */
  19.  
  20. #include "MacIncludes.h"
  21.  
  22. #include "Clipboard.h"
  23.  
  24.  
  25. // --------------------------------------------------------------------------------------------------------------
  26. // GLOBALS FOR THIS FILE ONLY
  27. // --------------------------------------------------------------------------------------------------------------
  28. static Handle            gScrapHandle;
  29. static long                gCurrentOffset;
  30. static QDProcsPtr          gSavedProcs;
  31. static QDProcs            gMyProcs;
  32. static CQDProcs            gMyColorProcs;
  33.  
  34. // --------------------------------------------------------------------------------------------------------------
  35. // INTERNAL ROUTINES
  36. // --------------------------------------------------------------------------------------------------------------
  37. static pascal void GetPICTData(Ptr dataPtr, short byteCount)
  38. /*
  39.     replacement for the QuickDraw bottleneck routine
  40. */
  41.     long    longCount = byteCount;
  42.     
  43.     BlockMoveData((*gScrapHandle)+gCurrentOffset, dataPtr, longCount);
  44.     gCurrentOffset += longCount;
  45.     
  46. } // GetPICTData
  47.  
  48. #if GENERATINGCFM
  49.     static RoutineDescriptor gGetPICTDataRD = BUILD_ROUTINE_DESCRIPTOR(uppQDGetPicProcInfo, GetPICTData);
  50.     static QDGetPicUPP gGetPICTData = &gGetPICTDataRD;
  51. #else
  52.     static QDGetPicUPP gGetPICTData = NewQDGetPicProc(GetPICTData);
  53. #endif
  54.  
  55. // --------------------------------------------------------------------------------------------------------------
  56.  
  57. static OSErr DrawPictureFromHandleAndOffset(
  58.     Rect    * pWhereToDraw,            // draw picture at this location
  59.     Handle    sourceHandle,            // handle containing data
  60.     long    sourceOffset)            // offset within handle to start at
  61. {
  62.     OSErr        anErr;
  63.     Rect        whereToDraw = *pWhereToDraw;
  64.     PicHandle    tempPict = (PicHandle) NewHandle(sizeof(Picture));
  65.     
  66.     anErr = MemError();
  67.     nrequire(anErr, FailedNewHandle);
  68.         
  69.     // calculate the rectangle in which to draw, save the picture header into
  70.     // our handle
  71.     {    
  72.     PicPtr    pPicture;
  73.     
  74.     pPicture = (PicPtr)((*sourceHandle) + sourceOffset);
  75.     whereToDraw.right = whereToDraw.left + pPicture->picFrame.right - pPicture->picFrame.left;
  76.     whereToDraw.bottom = whereToDraw.top + pPicture->picFrame.bottom - pPicture->picFrame.top;
  77.     BlockMoveData((Ptr)pPicture, (Ptr)*tempPict, sizeof(Picture));
  78.     }
  79.  
  80.     // store into globals for our GetPicProc in preparation for the draw
  81.     gScrapHandle = sourceHandle;
  82.     gCurrentOffset = sourceOffset + sizeof(Picture);
  83.  
  84.     // install our GetPic proc
  85.     if (gMachineInfo.theEnvirons.hasColorQD)
  86.         SetStdCProcs(&gMyColorProcs);
  87.     else
  88.         SetStdProcs(&gMyProcs);
  89.     gMyProcs.getPicProc = gGetPICTData;
  90.     gMyColorProcs.getPicProc = gGetPICTData;
  91.     gSavedProcs = (*qd.thePort).grafProcs;
  92.     if (gMachineInfo.theEnvirons.hasColorQD)
  93.         (*qd.thePort).grafProcs = (QDProcsPtr)&gMyColorProcs;
  94.     else
  95.         (*qd.thePort).grafProcs = &gMyProcs;
  96.     
  97.     // Draw the picture
  98.     DrawPicture(tempPict, &whereToDraw);
  99.     
  100.     // remove our GetPic proc
  101.     (*qd.thePort).grafProcs = gSavedProcs;
  102.  
  103.     DisposeHandle((Handle)tempPict);
  104.     
  105. // FALL THROUGH EXCEPTION HANDLING
  106. FailedNewHandle:
  107.     return anErr;
  108.     
  109. } // DrawPictureFromHandleAndOffset
  110.  
  111. // --------------------------------------------------------------------------------------------------------------
  112. // OOP INTERFACE ROUTINES
  113. // --------------------------------------------------------------------------------------------------------------
  114. static OSErr    ClipboardUpdateWindow(WindowRef pWindow, WindowDataPtr pData)
  115. {
  116. #pragma unused (pData)
  117.  
  118.     OSErr        anErr;
  119.     FontInfo    theInfo;
  120.     long        scrapResult;
  121.     long        offset;
  122.     ResType        validScrapType = '????';
  123.     Rect        topAreaRect;
  124.     RgnHandle    oldClip = NewRgn();
  125.     
  126.     // clear out any data that was there before
  127.     GetClip(oldClip);
  128.     EraseRect(&GetWindowPort(pWindow)->portRect);
  129.     
  130.     // get that scrap!
  131.     anErr = LoadScrap();
  132.     nrequire(anErr, LoadScrap);
  133.     
  134.     // figure out the scrap type and offset
  135.     {
  136.     short i = 0;
  137.     ResType        scrapTypes[] = {'TEXT', 'PICT', '????'};
  138.  
  139.     while (scrapTypes[i] != '????')
  140.         {
  141.         scrapResult = GetScrap(nil, scrapTypes[i], &offset);
  142.         if (scrapResult > 0)
  143.             {
  144.             validScrapType = scrapTypes[i];
  145.             break;
  146.             }
  147.         ++i;
  148.         }
  149.     }
  150.     
  151.     // setup for the drawing
  152.     TextFont(applFont);
  153.     TextSize(9);
  154.     GetFontInfo(&theInfo);
  155.  
  156.     // caclulate our area at the top to say what type of contents the scrap is
  157.     topAreaRect = GetWindowPort(pWindow)->portRect;
  158.     topAreaRect.bottom = topAreaRect.top + theInfo.ascent + theInfo.descent + theInfo.leading * 2 + 2;
  159.  
  160.     // draw two lines under the area to separate it from the rest of the window
  161.     MoveTo(topAreaRect.left, topAreaRect.bottom - 2);
  162.     Line(topAreaRect.right - topAreaRect.left, 0);
  163.     Move(0, 2);
  164.     Line(-(topAreaRect.right - topAreaRect.left), 0);
  165.  
  166.     // draw a string describing the contents
  167.     {
  168.     Str255    theString;
  169.     
  170.     switch (validScrapType)
  171.         {
  172.         case 'PICT':
  173.             GetIndString(theString, kClipboardStrings, iClipboardPICT);
  174.             break;
  175.             
  176.         case 'TEXT':
  177.             GetIndString(theString, kClipboardStrings, iClipboardText);
  178.             break;
  179.             
  180.         default:
  181.             if (InfoScrap()->scrapCount == 0)
  182.                 GetIndString(theString, kClipboardStrings, iClipboardNone);
  183.             else
  184.                 GetIndString(theString, kClipboardStrings, iClipboardUnknown);
  185.             break;
  186.         }
  187.         
  188.     MoveTo(topAreaRect.left + 4, topAreaRect.bottom - 4);
  189.     DrawString(theString);
  190.     }
  191.     
  192.     // calculate the part *not* in our top area    
  193.     topAreaRect.top = topAreaRect.bottom+1;
  194.     topAreaRect.bottom = GetWindowPort(pWindow)->portRect.bottom;
  195.  
  196.     // remember the scrap count -- if it changes, we do an update!
  197.     ((ClipboardDataPtr)pData)->scrapCount = InfoScrap()->scrapCount;
  198.  
  199.     // now, draw the contents, if we have a legal type to use
  200.     {
  201.     Rect    clipArea = topAreaRect;
  202.     Handle    scrapHandle = InfoScrap()->scrapHandle;
  203.     
  204.     clipArea.right -= 15;
  205.     clipArea.bottom -= 15;
  206.     ClipRect(&clipArea);
  207.     switch (validScrapType)
  208.         {
  209.         case 'PICT':
  210.             DrawPictureFromHandleAndOffset(&clipArea, 
  211.                     scrapHandle, offset);
  212.             break;
  213.             
  214.         case 'TEXT':
  215.             {
  216.             char    oldState;
  217.                     
  218.             oldState = HGetState(scrapHandle);
  219.             HLock(scrapHandle);
  220.             clipArea.right -= 15;
  221.             clipArea.bottom -= 15;
  222.             TETextBox(*scrapHandle+offset, scrapResult, &clipArea, teJustLeft);
  223.             }
  224.             break;
  225.         }
  226.     }
  227.     
  228.     // finally draw the grow icon, but omit our top area rect from the drawing
  229.     ClipRect(&topAreaRect);
  230.     DrawGrowIcon(pWindow);
  231.     
  232.     SetClip(oldClip);
  233.     DisposeRgn(oldClip);
  234.     
  235.     UnloadScrap();
  236.     
  237. // FALL THROUGH EXCEPTION HANDLING
  238. LoadScrap:
  239.     return anErr;
  240.     
  241. } // ClipboardUpdateWindow
  242.  
  243.  
  244. // --------------------------------------------------------------------------------------------------------------
  245.  
  246. static Boolean    ClipboardFilterEvent(WindowRef pWindow, WindowDataPtr pData, EventRecord *pEvent)
  247. {    
  248.  
  249.     // Force an update on scrap changes during activate/deactivate.
  250.  
  251.     switch (pEvent->what)
  252.         {
  253.         case nullEvent:
  254.         case activateEvt:
  255.             if (LoadScrap() == noErr)
  256.                 {
  257.                 PScrapStuff pScrap = InfoScrap();
  258.                 
  259.                 if (pScrap->scrapCount != ((ClipboardDataPtr)pData)->scrapCount)
  260.                     {
  261.                     GrafPtr    pPort = (GrafPtr)GetWindowPort(pWindow);
  262.                     
  263.                     SetPort(pPort);
  264.                     InvalRect(&pPort->portRect);
  265.                     }
  266.                 }
  267.             break;
  268.         
  269.         // Follow the HI guidelines and hide the clipboard when we are suspended.
  270.     
  271.         case osEvt:
  272.             if (((pEvent->message >> 24) & 0x0FF) == suspendResumeMessage)
  273.                 {
  274.                 if((pEvent->message & resumeFlag)==0)    // suspending
  275.                     {
  276.                     HideWindow(pWindow);
  277.                     pWindow = FrontWindow();
  278.                     if (pWindow)
  279.                         HiliteWindow(pWindow, false);
  280.                     }
  281.                 else                                    // resuming
  282.                     ShowWindow(pWindow);
  283.                 }
  284.             break;
  285.             
  286.         } // switch(what)
  287.     
  288.     return false;
  289.     
  290. } // ClipboardFilterEvent
  291.  
  292.  
  293. // --------------------------------------------------------------------------------------------------------------
  294.  
  295. static OSErr    ClipboardKeyEvent(WindowRef pWindow, WindowDataPtr pData, EventRecord *pEvent, Boolean isMotionKey)
  296. {    
  297.     #pragma unused(pWindow, pData, pEvent, isMotionKey)
  298.  
  299.     return noErr;
  300.  
  301. } // ClipboardKeyEvent
  302.  
  303.  
  304. // --------------------------------------------------------------------------------------------------------------
  305.  
  306. static OSErr    ClipboardGetBalloon(WindowRef pWindow, WindowDataPtr pData, 
  307.         Point *localMouse, short * returnedBalloonIndex, Rect *returnedRectangle)
  308. {
  309. #pragma unused (pWindow, pData, localMouse, returnedRectangle)
  310.  
  311.     *returnedBalloonIndex = iNoBalloon;
  312.     
  313.     return noErr;
  314.  
  315. } // ClipboardGetBalloon
  316.  
  317. // --------------------------------------------------------------------------------------------------------------
  318.  
  319. static OSErr    ClipboardGetDocumentRect(WindowRef pWindow, WindowDataPtr pData, 
  320.             LongRect * documentRectangle, Boolean forGrow)
  321. {
  322. #pragma unused (pWindow, pData, forGrow)
  323.     
  324.     Rect    maxSize = (**GetGrayRgn()).rgnBBox;
  325.     
  326.     RectToLongRect(&maxSize, documentRectangle);
  327.     
  328.     return noErr;
  329.     
  330. } // ClipboardGetDocumentRect
  331.  
  332.  
  333. // --------------------------------------------------------------------------------------------------------------
  334.  
  335. static OSErr    ClipboardCloseWindow(WindowRef pWindow, void* refCon)
  336. {    
  337. #pragma unused(pWindow,refCon)
  338.  
  339.     ChangeCommandName(cShowClipboard, kClipboardStrings, iClipboardShow);
  340.     UnloadScrap();
  341.     
  342.     return noErr;
  343.  
  344. } // ClipboardCloseWindow
  345.  
  346.  
  347. // --------------------------------------------------------------------------------------------------------------
  348.  
  349. static OSErr    ClipboardMakeWindow(WindowRef pWindow, WindowDataPtr pData)
  350. {
  351. #pragma unused (pWindow)
  352.  
  353.     pData->hasGrow                 = true;
  354.     pData->pFilterEvent         = (FilterEventProc)     ClipboardFilterEvent;
  355.     pData->pKeyEvent            = (KeyEventProc)         ClipboardKeyEvent;
  356.     pData->pGetBalloon            = (GetBalloonProc)         ClipboardGetBalloon;
  357.     pData->pUpdateWindow         = (UpdateWindowProc)     ClipboardUpdateWindow;
  358.     pData->pGetDocumentRect     = (GetDocumentRectProc) ClipboardGetDocumentRect;
  359.     pData->pCloseWindow            = (CloseWindowProc)        ClipboardCloseWindow;
  360.     
  361.     pData->contentRect.right = pData->contentRect.left + 
  362.                     qd.screenBits.bounds.right - qd.screenBits.bounds.left - 96;
  363.     pData->contentRect.bottom = pData->contentRect.top + 150;
  364.     MoveWindow(pWindow, 
  365.             qd.screenBits.bounds.left + 4, 
  366.             qd.screenBits.bounds.bottom - 154, false);
  367.     
  368.     ChangeCommandName(cShowClipboard, kClipboardStrings, iClipboardHide);
  369.  
  370.     return noErr;
  371.     
  372. } // ClipboardMakeWindow
  373.  
  374.  
  375. // --------------------------------------------------------------------------------------------------------------
  376.  
  377. OSErr    ClipboardPreflightWindow(PreflightPtr pPreflightData)
  378. {    
  379.     pPreflightData->resourceID            = kClipboardWindowID;
  380.     pPreflightData->continueWithOpen     = true;
  381.     pPreflightData->makeProcPtr         = ClipboardMakeWindow;
  382.     pPreflightData->storageSize         = sizeof(ClipboardDataRecord);
  383.     
  384.     return noErr;
  385.     
  386. } // ClipboardPreflightWindow
  387.  
  388. // --------------------------------------------------------------------------------------------------------------
  389.  
  390. void ClipboardGetFileTypes(OSType * pFileTypes, OSType * pDocumentTypes, short * numTypes)
  391. {
  392. #pragma unused (pFileTypes, pDocumentTypes, numTypes)
  393.  
  394. } // ClipboardGetFileTypes
  395.